/**
* @private
* @license	GNU GPLv2
*
* Copyright (C) 2007  Polly Jex.
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
* MA  02110-1301, USA.
*
* @see	http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/

package com.kirika.data.tda {
	
	/**
	 * @import
	 */
	
	import com.airlogger.AirLoggerDebug;
	import com.kirika.data.ICollection;
	import com.kirika.data.IQueue;
	import com.kirika.utils.TypeUtil;
	
	/**
	 * Modelo abstracto de una Cola.
	 * @author	Polly Jex (pollyjex@emc2zen.com.ar)
	 */
	public class AbstractQueue extends AbstractCollection implements IQueue {
		
		/**
		 * Capacidad de la coleccion.
		 */
		private var _capacity:uint;
		
		/**
		 * Constructor.
		 * @param	value		Estructura de datos.
		 * @param	capacity	Capacidad de la coleccion.
		 * @return	AbstractCollection
		 */
		public function AbstractQueue( value:Array = null, capacity:uint = 0 ) {
			
			if( ! TypeUtil.isNull( value ) && capacity > 0 ){
				value = value.slice( 0, capacity );
			}
			
			super( value );
			this._capacity = capacity;
			
		}
		
		/**
		 * Retorna la disponibilidad del Objeto.
		 * @return	Boolean
		 */
		public function available():Boolean {
			
			return ( this.size() < this.capacity() ) ? true : false;
			
		}
		
		/**
		 * Retorna la capacidad del Objeto.
		 * @return	uint
		 */
		public function capacity():uint {
			
			return this._capacity;
			
		}
		
		/**
		 * Retorna el primer elemento de la coleccion.
		 * @return	*
		 */
		public function element():* {
			
			if( this.size() > 0 ){
				return this.toSource()[0];
			}else{
				throw new Error( "The Collection this empty." );
			}
			
		}
		
		/**
		 * Inserta un elemento en la cola, si es posible.
		 * @param	value	Valor a insertar.
		 * @return	Boolean
		 */
		public function offer( value:* ):Boolean {
			
			return this.ResolveAdd( value );
			
		}
		
		/**
		 * Retorna el primer elemento de la coleccion, retorna <code>null</code> si la coleccion esta vacia.
		 * @return	*
		 */
		public function peek():* {
			
			var value:*;
			
			try{
				value = this.element();
			}catch( e:Error ){
				return null;	
			}
			
			return value;
			
		}
		
		/**
		 * Retorna y remueve, el primer elemento de la coleccion, retorna <code>null</code> si la coleccion esta vacia.
		 * @return	*
		 */
		public function poll():* {
			
			var value:* = this.peek();
			
			if( ! TypeUtil.isNull( value ) ){
				this.ResolveRemove( value );
			}
			
			return value;
			
		}
		
		/**
		 * Remueve el valor de la coleccion, si <code>value</code> es <code>null</code> se eliminara el primer elemento de la coleccion.
		 * @param	value	Elemento a remover.
		 * @return	Boolean
		 */
		public override function remove( value:* ):Boolean {			
			
			if( TypeUtil.isNull( value ) ){
				return ( ! TypeUtil.isNull( this.poll() ) ) ? true : false;
			}else{
				return this.ResolveRemove( value );
			}
			
		}
		
		/**
		 * Resuelve la insercion de uno o mas elementos a la coleccion.
		 * @param	value	Elemento/s a insertar.
		 * @return	Boolean
		 */
		protected override function ResolveAdd( value:* ):Boolean {
			
			
			if( ( ! TypeUtil.thisIs( value, ICollection ) && this.available() ) 
				|| ( TypeUtil.thisIs( value, ICollection ) && ( ( this.capacity() - this.size() ) >= value.size() ) ) ){
				
						return super.ResolveAdd( value );
				
			}else{
				
				return false;
				
			}
			
		}
					
	}
	
}